package com.pjc.db;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import com.mongodb.WriteResult;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * MongoUtils封装类
 * 
 * @author 王畅
 * @since 2015年6月21日
 */
public class MongoUtils {
	public static DBObject findAndModify(DBCollection dbColl, DBObject query, DBObject update) throws Exception {
		if (query == null)
			return null;
		DBObject obj = dbColl.findAndModify(query, null, null, false, update, true, false);
		if (obj != null)
			obj.removeField("_id");
		return obj;
	}

	public static DBObject findOne(DBCollection dbColl, DBObject ref) throws Exception {
		if (ref == null)
			throw new Exception("Para must not null!");
		DBObject obj = dbColl.findOne(ref);
		if (obj != null)
			obj.removeField("_id");
		return obj;
	}

	public static DBObject findOne(DBCollection dbColl, DBObject ref, DBObject field) throws Exception {
		if (ref == null)
			throw new Exception("Para must not null!");
		DBObject obj = dbColl.findOne(ref, field);
		if (obj != null)
			obj.removeField("_id");
		return obj;
	}

	public static WriteResult update(DBCollection dbColl, DBObject key, DBObject field) throws Exception {
		return dbColl.update(key, field, false, false, WriteConcern.SAFE);
	}

	public static WriteResult updateMulti(DBCollection dbColl, DBObject key, DBObject field) throws Exception {
		return dbColl.update(key, field, false, true, WriteConcern.SAFE);
	}

	public static WriteResult updateAll(DBCollection dbColl, DBObject key, DBObject val) throws Exception {
		if ((key == null) || (val == null)) {
			return null;
		}
		return dbColl.update(key, val, false, true, WriteConcern.SAFE);
	}

	public static WriteResult save(DBCollection dbColl, DBObject val) throws Exception {
		return dbColl.save(val, WriteConcern.SAFE);
	}

	public static WriteResult insert(DBCollection dbColl, List<DBObject> val) throws Exception {
		return dbColl.insert(val, WriteConcern.SAFE);
	}

	public static WriteResult insertOrUpdate(DBCollection dbColl, DBObject key, DBObject val) throws Exception {
		return dbColl.update(key, val, true, false, WriteConcern.SAFE);
	}

	public static WriteResult remove(DBCollection dbColl, DBObject query) throws Exception {
		return dbColl.remove(query, WriteConcern.SAFE);
	}

	public static DBObject convertFieldDBObject(Class<?> clazz) throws Exception {
		Field[] fields = clazz.getDeclaredFields();
		DBObject ref = new BasicDBObject();
		for (Field field : fields) {
			ref.put(field.getName(), "");
		}
		return ref;
	}

	@SuppressWarnings("unchecked")
	public static List<Map> findLimit(DBCollection dbColl, DBObject ref, int count) throws Exception {
		if (ref == null) {
			return null;
		}
		List list = new ArrayList();
		DBCursor cursor;
		if (count > 0)
			cursor = dbColl.find(ref).limit(count).sort(new BasicDBObject("time", Integer.valueOf(-1)));
		else {
			cursor = dbColl.find(ref).sort(new BasicDBObject("time", Integer.valueOf(-1)));
		}

		if (cursor == null)
			return list;
		try {
			do {
				DBObject val = cursor.next();
				Map map = val.toMap();
				if (map.containsKey("_id"))
					map.remove("_id");
				list.add(map);
			} while (cursor.hasNext());
		} finally {
			cursor.close();
		}
		return list;
	}

	public static DBCursor findAll(DBCollection dbColl, DBObject query, DBObject fields) throws Exception {
		if (query == null)
			query = new BasicDBObject();
		return dbColl.find(query, fields);
	}

	public static DBCursor findAll(DBCollection dbColl, DBObject query, DBObject fields, DBObject sort) throws Exception {
		if (query == null)
			query = new BasicDBObject();
		return dbColl.find(query, fields).sort(sort);
	}

	public static int findSize(DBCollection dbColl, DBObject ref, DBObject field) throws Exception {
		if (ref == null) {
			throw new IllegalArgumentException("Para must not null!");
		}
		return dbColl.find(ref, field).count();
	}

	public static long findCount(DBCollection dbColl) throws Exception {
		return dbColl.count();
	}

	public static long findCount(DBCollection dbColl, DBObject ref) throws Exception {
		return dbColl.find(ref).count();
	}

}
